package com.google.code.mochaccino.framework.util;
/*
 * Copyright 2012 Claude Houle claude.houle@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.joda.time.DateMidnight;
import org.joda.time.Days;
import org.joda.time.Hours;
import org.joda.time.LocalDate;
import org.joda.time.Minutes;
import org.joda.time.Months;
import org.joda.time.Seconds;
import org.joda.time.Weeks;
import org.joda.time.Years;

/** Utilities methods to manipulate dates. */
public final class DateUtil {

	private DateUtil() {
	}

	/** Chop Date Part */
	public static Calendar chopDate( Calendar cal ) {
		cal.set( Calendar.YEAR, 1970 );
		cal.set( Calendar.MONTH, Calendar.JANUARY );
		cal.set( Calendar.DAY_OF_MONTH, 1 );
		return cal;
	}

	/** Chop Date Part */
	public static Date chopDate( Date date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTime( date );
		cal = chopDate( cal );
		return cal.getTime();
	}

	/** Chop Date */
	public static Date chopDate( java.sql.Date date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTime( date );
		cal = chopDate( cal );
		return cal.getTime();
	}

	/** Chop Date Part */
	public static long chopDate( long date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTimeInMillis( date );
		cal = chopDate( cal );
		return cal.getTimeInMillis();
	}

	/** Chop Date Part */
	public static Time chopDate( Time date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTime( date );
		cal = chopDate( cal );
		return new Time( cal.getTimeInMillis() );
	}

	/** Chop Date Part */
	public static Timestamp chopDate( Timestamp date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTime( date );
		cal = chopDate( cal );
		return new Timestamp( cal.getTimeInMillis() );
	}

	/** Chop Time */
	public static Calendar chopTime( Calendar cal ) {
		cal.set( Calendar.HOUR, 0 );
		cal.set( Calendar.MINUTE, 0 );
		cal.set( Calendar.SECOND, 0 );
		cal.set( Calendar.MILLISECOND, 0 );
		cal.set( Calendar.AM_PM, Calendar.AM );
		return cal;
	}

	/** Chop Time */
	public static Date chopTime( Date date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTime( date );
		cal = chopTime( cal );
		return new Date( cal.getTimeInMillis() );
	}

	/** Chop Time */
	public static java.sql.Date chopTime( java.sql.Date date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTime( date );
		cal = chopTime( cal );
		return new java.sql.Date( cal.getTimeInMillis() );
	}

	/** Chop Time */
	public static long chopTime( long date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTimeInMillis( date );
		cal = chopTime( cal );
		return cal.getTimeInMillis();
	}

	/** Chop Time */
	public static Timestamp chopTime( Timestamp date ) {
		Calendar cal = new GregorianCalendar();
		cal.setTime( date );
		cal = chopTime( cal );
		return new Timestamp( cal.getTimeInMillis() );
	}

	/** Get Duration in Days */
	public static int getDurationInDays( Calendar start, Calendar end ) {
		return getDurationInDays( start.getTimeInMillis(), end.getTimeInMillis() );
	}

	/** Get Duration in Days */
	public static int getDurationInDays( Date start, Date end ) {
		return getDurationInDays( start.getTime(), end.getTime() );
	}

	/** Get Duration in Days */
	public static int getDurationInDays( long start, long end ) {
		Days d = Days.daysBetween( new LocalDate( start ), new LocalDate( end ) );
		return d.getDays();
	}

	/** Get Duration in Hours */
	public static int getDurationInHours( Calendar start, Calendar end ) {
		return getDurationInHours( start.getTimeInMillis(), end.getTimeInMillis() );
	}

	/** Get Duration in Hours */
	public static int getDurationInHours( Date start, Date end ) {
		return getDurationInHours( start.getTime(), end.getTime() );
	}

	/** Get Duration in Hours */
	public static int getDurationInHours( long start, long end ) {
		Hours d = Hours.hoursBetween( new LocalDate( start ), new LocalDate( end ) );
		return d.getHours();
	}

	/** Get Duration in Minutes */
	public static int getDurationInMinutes( Calendar start, Calendar end ) {
		return getDurationInMinutes( start.getTimeInMillis(), end.getTimeInMillis() );
	}

	/** Get Duration in Minutes */
	public static int getDurationInMinutes( Date start, Date end ) {
		return getDurationInMinutes( start.getTime(), end.getTime() );
	}

	/** Get Duration in Minutes */
	public static int getDurationInMinutes( long start, long end ) {
		Minutes d = Minutes.minutesBetween( new LocalDate( start ), new LocalDate( end ) );
		return d.getMinutes();
	}

	/** Get Duration in Months */
	public static int getDurationInMonths( Calendar start, Calendar end ) {
		return getDurationInMonths( start.getTimeInMillis(), end.getTimeInMillis() );
	}

	/** Get Duration in Months */
	public static int getDurationInMonths( Date start, Date end ) {
		return getDurationInMonths( start.getTime(), end.getTime() );
	}

	/** Get Duration in Months */
	public static int getDurationInMonths( long start, long end ) {
		Months d = Months.monthsBetween( new LocalDate( start ), new LocalDate( end ) );
		return d.getMonths();
	}

	/** Get Duration in Seconds */
	public static int getDurationInSeconds( Calendar start, Calendar end ) {
		return getDurationInSeconds( start.getTimeInMillis(), end.getTimeInMillis() );
	}

	/** Get Duration in Seconds */
	public static int getDurationInSeconds( Date start, Date end ) {
		return getDurationInSeconds( start.getTime(), end.getTime() );
	}

	/** Get Duration in Seconds */
	public static int getDurationInSeconds( long start, long end ) {
		Seconds d = Seconds.secondsBetween( new LocalDate( start ), new LocalDate( end ) );
		return d.getSeconds();
	}

	/** Get Duration in Weeks */
	public static int getDurationInWeeks( Calendar start, Calendar end ) {
		return getDurationInWeeks( start.getTimeInMillis(), end.getTimeInMillis() );
	}

	/** Get Duration in Weeks */
	public static int getDurationInWeeks( Date start, Date end ) {
		return getDurationInWeeks( start.getTime(), end.getTime() );
	}

	/** Get Duration in Weeks */
	public static int getDurationInWeeks( long start, long end ) {
		Weeks d = Weeks.weeksBetween( new LocalDate( start ), new LocalDate( end ) );
		return d.getWeeks();
	}

	/** Get Duration in Years */
	public static int getDurationInYears( Calendar start, Calendar end ) {
		return getDurationInYears( start.getTimeInMillis(), end.getTimeInMillis() );
	}

	/** Get Duration in Years */
	public static int getDurationInYears( Date start, Date end ) {
		return getDurationInYears( start.getTime(), end.getTime() );
	}

	/** Get Duration in Years */
	public static int getDurationInYears( long start, long end ) {
		Years d = Years.yearsBetween( new LocalDate( start ), new LocalDate( end ) );
		return d.getYears();
	}

	/**
	 * Is specified date between specified boundaries?
	 *
	 * @param start         Lower Boundary
	 * @param end           Upper Boundary
	 * @param specifiedDate Date to verify
	 */
	public static boolean isBetween( Calendar start, Calendar end, Calendar specifiedDate ) {
		return isBetween( start.getTimeInMillis(), end.getTimeInMillis(), specifiedDate.getTimeInMillis() );
	}

	/**
	 * Is specified date between specified boundaries?
	 *
	 * @param start         Lower Boundary
	 * @param end           Upper Boundary
	 * @param specifiedDate Date to verify
	 */
	public static boolean isBetween( Date start, Date end, Date specifiedDate ) {
		return isBetween( start.getTime(), end.getTime(), specifiedDate.getTime() );
	}

	/**
	 * Is specified date between specified boundaries?
	 *
	 * @param start         Lower Boundary
	 * @param end           Upper Boundary
	 * @param specifiedDate Date to verify
	 */
	public static boolean isBetween( long start, long end, long specifiedDate ) {
		if ( (specifiedDate >= start) && (specifiedDate <= end) ) {
			return true;
		}
		return false;
	}

	/** Return the minimum between the 2 values */
	public static Calendar max( Calendar first, Calendar second ) {
		if ( first.getTimeInMillis() >= second.getTimeInMillis() ) {
			return first;
		}
		return second;
	}

	/** Return the minimum between the 2 values */
	public static Date max( Date first, Date second ) {
		if ( first.getTime() >= second.getTime() ) {
			return first;
		}
		return second;
	}

	/** Return the minimum between the 2 values */
	public static java.sql.Date max( java.sql.Date first, java.sql.Date second ) {
		if ( first.getTime() >= second.getTime() ) {
			return first;
		}
		return second;
	}

	/** Return the minimum between the 2 values */
	public static Timestamp max( Timestamp first, Timestamp second ) {
		if ( first.getTime() >= second.getTime() ) {
			return first;
		}
		return second;
	}

	/** Return the minimum between the 2 values */
	public static Calendar min( Calendar first, Calendar second ) {
		if ( first.getTimeInMillis() <= second.getTimeInMillis() ) {
			return first;
		}
		return second;
	}

	/** Return the minimum between the 2 values */
	public static Date min( Date first, Date second ) {
		if ( first.getTime() <= second.getTime() ) {
			return first;
		}
		return second;
	}

	/** Return the minimum between the 2 values */
	public static java.sql.Date min( java.sql.Date first, java.sql.Date second ) {
		if ( first.getTime() <= second.getTime() ) {
			return first;
		}
		return second;
	}

	/** Return the minimum between the 2 values */
	public static Timestamp min( Timestamp first, Timestamp second ) {
		if ( first.getTime() <= second.getTime() ) {
			return first;
		}
		return second;
	}

	/** Return the today's date without HH:mm:ss precision. */
	public static Calendar todayAsCalendar() {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTimeInMillis( todayAsMillis() );
		return cal;
	}

	/** Return the today's date without HH:mm:ss precision. */
	public static Date todayAsDate() {
		return new Date( todayAsMillis() );
	}

	/** Return the today's date without HH:mm:ss precision. */
	public static long todayAsMillis() {
		DateMidnight d = new DateMidnight( System.currentTimeMillis() );
		return d.getMillis();
	}

	/** Return the today's date without HH:mm:ss precision. */
	public static Date todayAsSqlDate() {
		return new java.sql.Date( todayAsMillis() );
	}

	/** Return the today's date without HH:mm:ss precision. */
	public static Date todayAsTimestamp() {
		return new Timestamp( todayAsMillis() );
	}
}